import asyncio
async def check_port(ip, port):
    try:
        # 尝试连接到目标IP和端口
        reader, writer = await asyncio.wait_for(asyncio.open_connection(ip, port), timeout=1)
        writer.close()
        await writer.wait_closed()
        return port  # 返回端口号表示端口开放
    except (asyncio.TimeoutError, ConnectionRefusedError, OSError):
        # 如果连接超时、被拒绝或发生其他网络错误，忽略该端口
        return None
    except Exception as e:
        # 其他异常
        print(f"Error on port {port}: {e}")
        return None

async def scan_ports(ip, port_range=None, specific_ports=None):
    # 创建一个空的端口列表
    ports_to_scan = []
    # 如果提供了端口范围，则生成该范围内的所有端口
    if port_range:
        start_port, end_port = port_range
        ports_to_scan.extend(range(start_port, end_port + 1))
    # 如果提供了具体端口，则将它们添加到端口列表中
    if specific_ports:
        ports_to_scan.extend(specific_ports)
    # 去重并排序
    ports_to_scan = sorted(set(ports_to_scan))
    # 为每个端口创建一个任务
    tasks = [check_port(ip, port) for port in ports_to_scan]
    # 并发运行所有任务并收集结果
    results = await asyncio.gather(*tasks)
    # 收集所有开放的端口
    open_ports = [port for port in results if port is not None]
    # print(f"Open ports: {open_ports}")
    # 检查是否有开放的端口，并输出相应信息
    return open_ports

    # if open_ports:
    #     print(f"Open ports on {ip}: {open_ports}")
    # else:
    #     print(f"No open ports found on {ip}.")
if __name__ == "__main__":
    target_ip = "192.168.43.178"  # 替换为要扫描的目标IP
    # asyncio.run(scan_ports(target_ip, port_range=(1, 1024)))
    # asyncio.run(scan_ports(target_ip, specific_ports=[445]))
    result = asyncio.run(scan_ports(target_ip, port_range=None, specific_ports=[20, 21, 22, 23, 25, 53, 67, 68, 80, 110, 123, 139, 135 ,143, 161, 194,
                                                                220, 389, 443, 445, 465, 514, 512, 513, 543, 554, 587, 631,902,912,
                                                                8080, 8443, 3306, 5432, 6379, 9200, 11211]))
    print(result)
